////////////////////////////////////////////////////////////////////////////////
//
//  TYPHOON FRAMEWORK
//  Copyright 2013, Typhoon Framework Contributors
//  All Rights Reserved.
//
//  NOTICE: The authors permit you to use, modify, and distribute this file
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////


#import "TyphoonDefinition.h"
#import "TyphoonInjectionsEnumeration.h"

@protocol TyphoonPropertyInjection;


/**
 * Declares definition methods & properties that may be useful for building infrastructure components.
 *
 * Normally you won't need to use these, but they are available for advanced usage via Typhoon+Infrastructure.h.
 */
@interface TyphoonDefinition (/* Infrastructure */)

/**
 * The key of the component. A key is useful when multiple configuration of the same class or protocol are desired - for example
 * MasterCardPaymentClient and VisaPaymentClient.
 *
 * If using the TyphoonBlockComponentFactory style of assembly, the key is automatically generated based on the selector name of the
 * component, thus avoiding "magic strings" and providing better integration with IDE refactoring tools.
 */
@property (nonatomic) NSString *key;

/**
 * Describes the initializer, ie the selector and arguments that will be used to instantiate this component.
 *
 * An initializer can be an instance method, a class method, or even a reference to another component's method (see factory property).
 *
 * If no explicit initializer has been set, returns a default initializer representing the init method.
 *
 * @see factory
 */
@property (nonatomic, readonly) TyphoonMethod *initializer;

/**
 * Returns true if this is a default initializer generated by Typhoon. A manually specified initializer will return false, even if the
 * selector is @selector(init).
 */
@property (nonatomic, getter = isInitializerGenerated) BOOL initializerGenerated;

/**
 * A method injection object configured using performBeforeInjections:parameters:.
 */
@property (nonatomic, readonly) TyphoonMethod *beforeInjections;

/**
 * Describes injected properties, represented by objects conforming to TyphoonPropertyInjection protocol.
 */
@property (nonatomic, readonly) NSSet *injectedProperties;

/**
 * Describes injected methods, represented by TyphoonMethod objects.
 */
@property (nonatomic, readonly) NSOrderedSet *injectedMethods;

/**
 * A method injection object configured using performAfterInjections:parameters:.
 */
@property (nonatomic, readonly) TyphoonMethod *afterInjections;

@property (nonatomic, readonly) SEL afterAllInjections;

- (instancetype)initWithClass:(Class)clazz key:(NSString *)key;

+ (instancetype)withClass:(Class)clazz key:(NSString *)key;


- (BOOL)hasRuntimeArgumentInjections;

- (BOOL)isCandidateForInjectedClass:(Class)clazz includeSubclasses:(BOOL)includeSubclasses;

- (BOOL)isCandidateForInjectedProtocol:(Protocol *)aProtocol;


- (void)addInjectedProperty:(id<TyphoonPropertyInjection>)property;

- (void)addInjectedPropertyIfNotExists:(id<TyphoonPropertyInjection>)property;

- (void)enumerateInjectionsOfKind:(Class)injectionClass options:(TyphoonInjectionsEnumerationOption)options
                       usingBlock:(TyphoonInjectionsEnumerationBlock)block;

@end
